/*-
 * Copyright notice
 * 
 * (c) 2011 Christian Würtz <christian.wuertz@googlemail.com>
 * 
 * All rights reserved.
 * 
 * This file is part of the google-static-map-url-builder project. It is free
 * software: you can redistribute it and/or modify it under the terms of the 
 * GNU General Public License as published by the Free Software Foundation,
 * either version 2 of the License, or (at your option) any later version.
 * 
 * The google-static-map-url-builder is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 
 * Public License for more details.
 *  
 * You should have received a copy of the GNU General Public License
 * along with the google-static-map-url-builder. If not, see 
 * <http://www.gnu.org/licenses/>.
 */
package de.wuertz.map.types;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import de.wuertz.map.enumeration.Color;
import de.wuertz.map.exception.InvalidParameterException;

/**
 * A static path on a map.
 * 
 * TODO: Support of fillcolor and addresses as coordinates.
 * 
 * @author Christian Würtz <christian.wuertz@googlemail.com>
 */
public class Path
{
	/**
	 * This pattern describes a 24-bit color in it's hexadecimal representation.
	 */
	private static final Pattern COLOR_PATTERN = Pattern.compile( "^0x?(([a-fA-F0-9]){3}){1,2}$" );

	/**
	 * (Optional)
	 * 
	 * The thickness of the path in pixels.
	 */
	private int weight;

	/**
	 * (Optional)
	 * 
	 * The marker's color.
	 */
	private String color;

	/**
	 * The path is defined by this coordinates.
	 */
	private ArrayList<Coordinate> coordinates;

	/**
	 * Constructor.
	 */
	public Path()
	{
		// Initialize some objects.
		this.coordinates = new ArrayList<Coordinate>();
		this.weight = 5;
	}

	/**
	 * Get the thickness of the path in pixels.
	 * 
	 * @return The thickness of the path in pixels.
	 */
	public int getWeight()
	{
		return this.weight;
	}

	/**
	 * (Optional)
	 * 
	 * Set the thickness of the path in pixels.
	 * 
	 * @param weight The the thickness of the path in pixels.
	 * 
	 * @throws InvalidParameterException
	 */
	public void setWeight( int weight ) throws InvalidParameterException
	{
		// Check whether a positive value bigger than 0 was given.
		if( weight > 0 )
		{
			this.weight = weight;
		}
		else
		{
			throw new InvalidParameterException( "The weight must be bigger than zero." );
		}
	}

	/**
	 * Get the color.
	 * 
	 * @return The color.
	 */
	public String getColor()
	{
		return this.color;
	}

	/**
	 * (Optional)
	 * 
	 * Set the color.
	 * 
	 * @param color The color to set.
	 */
	public void setColor( Color color )
	{
		this.color = color.toString();
	}

	/**
	 * (Optional)
	 * 
	 * Set the color.
	 * 
	 * @param color The color to set.
	 * 
	 * @throws InvalidParameterException
	 */
	public void setColor( String color ) throws InvalidParameterException
	{
		// Check whether the string contains a valid color representation.
		Matcher matcher = COLOR_PATTERN.matcher( color );
		if( matcher.matches() )
		{
			this.color = color.toString();
		}
		else
		{
			throw new InvalidParameterException(
					"The color representation is invalid. Must be in the format of \"0xF0F0F0\"" );
		}
	}

	/**
	 * Get coordinates that define this path.
	 * 
	 * @return The coordinates that define this path.
	 */
	public ArrayList<Coordinate> getCoordinates()
	{
		return this.coordinates;
	}

	/**
	 * Add a coordinate to that path to extend it.
	 * 
	 * @param coordinate The new element of the path.
	 */
	public void addCoordinate( Coordinate coordinate )
	{
		this.coordinates.add( coordinate );
	}

	/**
	 * Get the representation of this path as it will be used in the URL to access Google's static
	 * maps API.
	 * 
	 * @return This path's URL representation.
	 */
	public String getURLRepresentation()
	{
		// Create the builder that creates the URL representation of this marker.
		StringBuilder builder = new StringBuilder( 256 );
		builder.append( "&" );
		builder.append( "path=" );

		// If specified, set the color of this marker.
		if( this.color != null )
		{
			builder.append( "color:" );
			builder.append( this.color.toString() );
			builder.append( "|" );
		}

		// If the weight isn't the default value of 5, set it.
		if( this.weight != 5 )
		{
			builder.append( "weight:" );
			builder.append( this.weight );
			builder.append( "|" );
		}

		// Add the coordinates that define this path.
		for( int i = 0; i < this.coordinates.size(); i++ )
		{
			builder.append( this.coordinates.get( i ).toString() );

			// Don't add a | after the last coordinate.
			if( i != this.coordinates.size() - 1 )
			{
				builder.append( "|" );
			}
		}

		return builder.toString();
	}
}
